package com.xinyue.server.framework.server.socket;

import com.google.common.util.concurrent.RateLimiter;
import com.xinyue.server.framework.common.GameFrameworkConfig;
import com.xinyue.server.framework.handler.GameChannelConfirmHandler;
import com.xinyue.server.framework.handler.GameRequestDispatcherHandler;
import com.xinyue.server.framework.server.RequestFilterHandler;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.timeout.IdleStateHandler;
import org.springframework.context.ApplicationContext;

/**
 * netty socket 长连接的channel初始化工具，如果是开发tcp长连接游戏，使用这个channel初始化器
 *
 * @Author 王广帅
 * @Date 2021/1/24 17:20
 */
public class SocketServerChannelInitializer extends ChannelInitializer<Channel> {

    private ApplicationContext context;
    /**
     * 全局请求QPS限制器
     */
    private RateLimiter globalLimiter;


    public SocketServerChannelInitializer(ApplicationContext context) {
        this.context = context;
        GameFrameworkConfig gameFrameworkConfig = context.getBean(GameFrameworkConfig.class);
        globalLimiter = RateLimiter.create(gameFrameworkConfig.getGlobalRequestQps());
    }

    @Override
    protected void initChannel(Channel ch) {
        GameFrameworkConfig gameFrameworkConfig = context.getBean(GameFrameworkConfig.class);
        ChannelPipeline p = ch.pipeline();
        int allIdleTimeSeconds = gameFrameworkConfig.getMaxIdleTime();
        p.addLast(new IdleStateHandler(0, 0, allIdleTimeSeconds));
        // 创建QPS限制器
        RateLimiter singleLimiter = RateLimiter.create(gameFrameworkConfig.getRequestQps());
        p.addLast(new RequestFilterHandler(globalLimiter, singleLimiter));
        // 添加拆包
        p.addLast(new LengthFieldBasedFrameDecoder(gameFrameworkConfig.getMaxFrameLength(), 0, 4, -4, 0));

        // 添加接收消息的解码handler
        p.addLast(new SocketDecoderHandler());
        // 返回消息的编码handler
        p.addLast(new SocketEncoderHandler());
        // 添加连接通道确认handler
        GameChannelConfirmHandler channelConfirmHandler = context.getBean(GameChannelConfirmHandler.class);
        p.addLast(channelConfirmHandler);
        // 添加业务处理handler
        GameRequestDispatcherHandler requestDispatcherHandler = context.getBean(GameRequestDispatcherHandler.class);
        p.addLast(requestDispatcherHandler);


    }

}
